package edu.harvard.hul.util;

/* @author Dave Siegel
*
*/

       
import java.io.*;
import java.util.*;
import java.net.*;

import java.awt.Color;
import java.text.SimpleDateFormat;

import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;

import com.esri.aims.mtier.model.map.*;
import com.esri.aims.mtier.model.map.layer.*;
import com.esri.aims.mtier.model.map.layer.renderer.symbol.*;
import com.esri.aims.mtier.model.map.layer.renderer.*;
import com.esri.aims.mtier.model.map.layer.query.*;
import com.esri.aims.mtier.model.arcmap.Scale;
import com.esri.aims.mtier.model.util.DoubleConversion;
import com.esri.aims.mtier.model.envelope.Envelope;
import com.esri.aims.mtier.model.acetate.*;

import com.esri.aims.mtier.io.*;
import com.esri.aims.mtier.model.admin.*;
import com.esri.aims.mtier.model.axl.*;
       
import com.esri.sde.sdk.pe.*;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;  // Used during SDE raster clipping

import edu.harvard.hul.ois.hgl.beans.hglSearchResultBean;

import java.net.*;
import org.xml.sax.*;
import java.sql.*;

/* Used for email validation */
import java.util.regex.*;
import oracle.sql.CLOB;

public class HGLUtilities extends java.lang.Object {
    
    private static String user;
    private static String password;
    private static String pass;
    private static String server;
    private static String jdbcConnect;
    private static String driver = "oracle.jdbc.OracleDriver";
    private static String shostname = "alcott.hul.harvard.edu";
    private static String susername = "";
    private static String spassword = "";
    
    private static final Set fCOMMON_WORDS = new HashSet();
    private static final String fDOUBLE_QUOTE = "\"";

    //the parser flips between these two sets of delimiters
    private static final String fWHITESPACE_AND_QUOTES = " \t\r\n\"";
    private static final String fQUOTES_ONLY ="\"";

    /**
    * Very common words against which searches will not be
    * performed.
    */
    static {
      fCOMMON_WORDS.add("a");
      fCOMMON_WORDS.add("and");
      fCOMMON_WORDS.add("be");
      fCOMMON_WORDS.add("for");
      fCOMMON_WORDS.add("from");
      fCOMMON_WORDS.add("has");
      fCOMMON_WORDS.add("i");
      fCOMMON_WORDS.add("in");
      fCOMMON_WORDS.add("is");
      fCOMMON_WORDS.add("it");
      fCOMMON_WORDS.add("of");
      fCOMMON_WORDS.add("on");
      fCOMMON_WORDS.add("to");
      fCOMMON_WORDS.add("the");
    }
        
    /**
     * Constructor
    */
    public HGLUtilities() {
        getProps();
    } 
      
    public void getProps() {

        Properties props = new Properties();
    
        //try retrieve data from file
        //catch exception in case properties file does not exist

        try {
            props.load(new FileInputStream("opengeoportal.properties"));
            user = props.getProperty("user");
            password = props.getProperty("password");
            pass = props.getProperty("password");
            server = props.getProperty("server");
            jdbcConnect = props.getProperty("jdbcConnection");

            shostname = props.getProperty("shostname");
            susername = props.getProperty("susername");
            spassword = props.getProperty("spassword");

            //If value of message variable is null assign default value "Hello World"
            if(user == null) {
              user = new String("cga");
              password = "cgabrowse";
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
      /*
       * Force a 900913 projection
       */
      
      public static double[] ll2meters(double lat, double lon) throws IOException {
          
          double originShift = 2 * Math.PI * 6378137 / 2.0; 
          double[] ret = new double[2];
          double mx=0; 
          double my=0;
          mx = lon * originShift / 180.0;
          my = Math.log(Math.tan((90 + lat) * Math.PI / 360.0 )) / (Math.PI / 180.0);
          my = my * originShift / 180.0;
          ret[0] = mx;
          ret[1] = my;
          
          return ret;
           
            /*function ll2meters(lat,lon) {
                   // Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:900913
                   var originShift = 2 * Math.PI * 6378137 / 2.0;                     
                   var ret = new Array(); 
                   mx=0; my=0;
                   mx = lon * originShift / 180.0;
                   my = Math.log(Math.tan((90 + lat) * Math.PI / 360.0 )) / (Math.PI / 180.0);
                   my = my * originShift / 180.0;
                   ret.x = mx;
                   ret.y = my; 
                   return ret;
                }*/
      }

      /** Get a partial projection string for a particular layer
       * @param int layerName Layer ID to look at
       * @return String A projection string
       */
      public static String getFullProjectionString(int layerID) throws IOException {
          
        String projection = "";
        String intermediateProj = "";
        String testString = "";
        int startPos=0, endPos=0;
        
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "select a.srid, b.srid, b.srtext from layers a, " +
                          "spatial_references b where b.srid = a.srid and a.layer_id = " + layerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    projection = rs.getString("srtext");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
      
          return projection;
      }
      
      /** Get a partial projection string for a particular layer
       * @param int layerName Layer ID to look at
       * @return String A projection string
       */
      public static String getArcIMSProjectionString(int layerID) throws IOException {
          
        String projection = "";
        String intermediateProj = "";
        String testString = "";
        int startPos=0, endPos=0;
        
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "select a.srid, b.srid, b.srtext from layers a, " +
                          "spatial_references b where b.srid = a.srid and a.layer_id = " + layerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    projection = rs.getString("srtext");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
      
        /* Parse out the entire projection string to something usable */
        intermediateProj = projection;
        startPos = intermediateProj.indexOf("[");
        endPos = intermediateProj.indexOf(",");
        
        /* Sometimes,  intermediateProj == UNKNOWN */
        if (!intermediateProj.equalsIgnoreCase("UNKNOWN") && endPos < projection.length()) {
            projection = intermediateProj.substring(startPos + 2, endPos - 1);
        } else {
            projection = "4326";
        }
        
          return projection;
      }
      
      /** Get a description for a particular layer
       * @param int layerID Layer ID to look at
       * @return String A projection string
       */
      public static int[] getListOfLayerIDs(int startLayerID, int endLayerID) throws IOException {
          
        int[] layers = new int[8000];
        int counter = 0;
        
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT HGL_LAYER_ID FROM GS_NEW WHERE HGL_LAYER_ID >= "+startLayerID+" AND HGL_LAYER_ID <= "+ endLayerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                while (rs.next()) {
                    layers[counter] = rs.getInt("HGL_LAYER_ID");
                    counter++;
                  }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
          
          return layers;
      }
      
      /** Get a description for a particular layer
       * @param int layerID Layer ID to look at
       * @return String A projection string
       */
      public static String getLayerDescription(int layerID) throws IOException {
          
        String description = "";
        
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT DESCRIPTION FROM GS_NEW WHERE HGL_LAYER_ID = " + layerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    description = rs.getString("DESCRIPTION");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
          
          return description;
      }
      
      /** Get a table_name of a particular layer
       * @param int layerID Layer ID to look at
       * @return String A table_name string
       */
      public static String getTablename(int layerID) throws IOException {
          
        String layerName = "";
        
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT TABLE_NAME FROM GS_NEW WHERE HGL_LAYER_ID = " + layerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    layerName = rs.getString("TABLE_NAME");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
          
          return layerName;
      }
      
      /** Get a full projection string for a particular layer
       * @param int layerID Layer ID to look at
       * @return String A projection string
       */
      public static String getProjectionString(int layerID) throws IOException {
          
        String projection = "";
        
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "select a.srid, b.srid, b.srtext from layers a, " +
                          "spatial_references b where b.srid = a.srid and a.layer_id = " + layerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    projection = rs.getString("srtext");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
          
          return projection;
      }
      
      /** Get an SDE layer's bounding coordinates as lat/long from meta table GS_NEW
       * @return double coordinates
       */
      public static double[] getLayerBoundingCoordsFromGS_NEW(int layerID) throws IOException {

        double[] layerCoords = new double[4];
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT MAXX, MAXY, MINX, MINY FROM GS_NEW WHERE HGL_LAYER_ID = " + layerID;

        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()) {
                    layerCoords[0] = rs.getDouble("MINX");
                    layerCoords[1] = rs.getDouble("MINY");
                    layerCoords[2] = rs.getDouble("MAXX");
                    layerCoords[3] = rs.getDouble("MAXY");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          return layerCoords;
      }
      
      /** Get an SDE layer ID
       * @param String layer name
       * @return int Layer ID
       */
      public static int[] getDRSBaseIDforRC(String layerName, int F, float[] envelope) throws IOException {
          
        int layerID = 0;
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT DRS_ID FROM GLOBAL_RASTER WHERE CAT_TILE_NAME IN  (SELECT NAME FROM '" + layerName + "' WHERE SHAPE IN " +
               "(SELECT FID FROM  F" + F + " WHERE EMINX > "+ envelope[0] +
               " AND EXAMX < "+ envelope[2] +" AND EMINY > " + envelope[10] +
               " AND EMAXY < " + envelope[3] + " ) ORDER BY NAME)";
        
        String driver = "oracle.jdbc.OracleDriver";
        int[] theID = new int[25];
        int counter = 0;

         
            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

               while (rs.next()) {
                 theID[counter] = rs.getInt("DRS_ID");
                 counter++;
                    if (counter > 10) // only allow up to 10 tiles for now
                        break;
               }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          return theID;
      }
      
      /** Get an SDE layer's bounding corrds
       * @return int Layer ID
       */
      public static double[] getSDELayerBoundingCoords(int layerID) throws IOException {

        double[] layerCoords = new double[4];
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT MAXX, MAXY, MINX, MINY FROM LAYERS WHERE LAYER_ID = " + layerID;
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()) {
                    layerCoords[0] = rs.getDouble("MINX");
                    layerCoords[1] = rs.getDouble("MINY");
                    layerCoords[2] = rs.getDouble("MAXX");
                    layerCoords[3] = rs.getDouble("MAXY");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          return layerCoords;
      }

      /** Get an SDE layer ID
       * @param String layer name
       * @return int Layer ID
       */
      public static int getSDELayerID(String layer) throws IOException {
          
        int layerID = 0;
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT LAYER_ID FROM LAYERS WHERE TABLE_NAME = '"+layer+"'";
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    layerID = rs.getInt("LAYER_ID");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          return layerID;
      }

      /** Get FGDC metadata for a downloadable HGL resource.
       * @param LayerName - HGL_TABLE_NAME from the ArcSDE LAYERS table
       * @return String The metadata XML
       */
      public static String getFGDCMetadataAsString(String LayerName) throws IOException {
          
        String theDTD = "<!DOCTYPE metadata SYSTEM \"http://hgl.harvard.edu:8080/HGL/html/fgdc-std-001-1998.dtd\"><metadata>";
        String fgdcRecord = "";
        String resultLine = "UNSET";
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "select e.met_xml.getClobval() as myxml from gs_new e WHERE TABLE_NAME = '"+LayerName.trim()+"'";
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    CLOB clob = (CLOB) rs.getClob(1);
                    Reader clobReader = clob.getCharacterStream();

                    // Get optimal size to read/write data and initialze buffer
                    char[] buffer = new char[clob.getBufferSize()];
                    int read = 0;
                    int bufflen = buffer.length;

                        while( (read = clobReader.read(buffer,0,bufflen)) > 0) {
                            fgdcRecord = fgdcRecord + new String( buffer, 0, read);
                        }
                    
                    clobReader.close();
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          fgdcRecord = fgdcRecord.replaceFirst("<metadata>", theDTD);
          return fgdcRecord;
          
      }
      
      
      /** Get information for an offline resource location
       * @param int layerID The layer ID
       * @return String The location of the resource
       */
      public static String getOfflineResourceLocation(int lookup_id) throws IOException {
          
        String resultLine = "UNSET";
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT EXTRACTVALUE(e.met_xml, '/metadata/distinfo/stdorder/ordering') AS MYRESOURCE FROM gs_new e WHERE HGL_LAYER_ID = " + lookup_id;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    resultLine = rs.getString("MYRESOURCE");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          return resultLine;
          
      }
      
      /** Get the SDE user that owns this layer
       * @param int layerID The layer ID
       * @return String The owner, SDE, SDE2 etc...
       */
      public static String getSDELayerOwner(String layer) throws IOException {
          
        String owner = "SDE";
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT OWNER FROM LAYERS WHERE TABLE_NAME = '" + layer + "'";
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    owner = rs.getString("OWNER");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          
          return owner;
      }
      
      /** Get the geometry type of a layer
       * @param int layerID The layer ID
       * @return int The geometry type
       */
      public static int getLayerGeometryType(int layerID) throws IOException {
          
        int type = 0;
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT geometry_type AS geometry FROM GS_NEW WHERE HGL_LAYER_ID = "+ layerID;
        
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    type = rs.getInt("geometry");
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
          
          return type;
      }
      
      /** Get a projection ID from the database
       * @param prjString String with projection descriptor
       * @return Projection ID for ArcIMS
       */
      public static int getArcIMSProjectionID(String prjString) {
          
        int prj = 0;
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

        String theQuery = "SELECT PROJECTION_ID, PROJECTION FROM IMSPROJECTIONS WHERE PROJECTION = '" + prjString + "'";
        String driver = "oracle.jdbc.OracleDriver";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    prj = rs.getInt("PROJECTION_ID");
                } else {
                    prj = 4326;
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
        return prj;
      }
      
      /** See if a raster is an SDE raster LAYER or raster CATALOG
       *@param layerName Layer name in question
       *@return type 1 = Raster Catalog
       *             2 = Raster
       *             3 = Scanned Map
       */
      public static int getRasterLayerType(String layerName) throws IOException {
          
          
        int retType = 3;
        
        String theQuery = "SELECT DRS_ID FROM GLOBAL_RASTER WHERE UPPER(TRIM(HGL_TABLE_NAME)) = '" + layerName.toUpperCase().trim() + "'";
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                while (rs.next()){
                 if (rs.getInt("DRS_ID") == 99) {
                    retType = 0;
                    break;
                 }
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        /* retType = 3 if it's a scanned map, and 0 if it's a raster type. If it's a
         * raster type, see if it's a raster catalog or just a raster */
        theQuery = "SELECT DISTINCT COLUMN_NAME FROM COLUMN_REGISTRY WHERE TABLE_NAME = '" + layerName.trim() + "'";
        
        if (retType == 0) {
            /* Set it as just a raster till proved otherwise */
            retType = 2;
            
            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                while (rs.next()){
                 if (rs.getString("COLUMN_NAME").equalsIgnoreCase("NAME")) {
                    retType = 1;
                    break;
                 }
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
        return retType;
        
      }

          
          
      /** Get total number of published HGL records
       * @param none
       * @return int Number of layers in production
       */
      public static int getTotalLayersInCollection() {
        int tot = 0;
        java.sql.ResultSet _resultSet = null;
        java.sql.Connection _con = null;
        
        String theQuery = "SELECT COUNT(*) AS MYNUM FROM GS_NEW";

            try {
                Class.forName(driver).newInstance();
                _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                Statement stmnt = _con.createStatement();
                ResultSet rs = stmnt.executeQuery(theQuery);

                if (rs.next()){
                    tot = rs.getInt("MYNUM");
                } else {
                    tot = 6700;
                }

                rs.close();
                stmnt.close();
                _con.close();

            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
        return tot;
      }

      /** parse an instance of <code>Color</code> from a <code>String</code> of form "R,G,B".
         * @param rgb RGB value as "200,200,200"
         * @return parsed Color.
         */
        public static Color parseColor(String rgb) {
            try {
                java.util.StringTokenizer st = new java.util.StringTokenizer(rgb,", ");
                int r = Integer.parseInt(st.nextToken());
                int g = Integer.parseInt(st.nextToken());
                int b = Integer.parseInt(st.nextToken());
                return new Color(r,g,b);
            } catch(Exception e){ }
            return null;
        }

        /**
         * Parse the user's search box input into a Set of String tokens.
         *
         * @return Set of Strings, one for each word in fSearchText; here "word"
         * is defined as either a lone word surrounded by whitespace, or as a series
         * of words surrounded by double quotes, "like this"; also, very common
         * words (and, the, etc.) do not qualify as possible search targets.
        */ 
        public static String[] parseSearchText(String fSearchText) {
            
            Set fCOMMON_WORDS = new HashSet();
            String fDOUBLE_QUOTE = "\"";

            //the parser flips between these two sets of delimiters
            String fWHITESPACE_AND_QUOTES = " \t\r\n\"";
            String fQUOTES_ONLY ="\"";
            
            Set result = new HashSet();

            boolean returnTokens = true;
            String currentDelims = fWHITESPACE_AND_QUOTES;
            StringTokenizer parser = new StringTokenizer(
                fSearchText,
                currentDelims,
                returnTokens );

            String token = null;
            while ( parser.hasMoreTokens() ) {
              token = parser.nextToken(currentDelims);
                if ( !isDoubleQuote(token) ){
                  addNonTrivialWordToResult( token, result );
                } else {
                  currentDelims = flipDelimiters(currentDelims);
                }
            }
            
           String[] theText = (String[])result.toArray(new String[result.size()]);
           return theText;
        }
        
          /**
          * Use to determine if a particular word entered in the
          * search box should be discarded from the search.
          */
          private static boolean isCommonWord( String aSearchTokenCandidate ) {
            return fCOMMON_WORDS.contains(aSearchTokenCandidate);
          }

          private static boolean textHasContent(String aText) {
            return (aText != null) && (!aText.trim().equals(""));
          }

          private static void addNonTrivialWordToResult( String aToken, Set aResult ){
            if ( textHasContent(aToken) && !isCommonWord(aToken.trim()) ) {
              aResult.add( aToken.trim() );
            }
          }

          private static boolean isDoubleQuote( String aToken ){
            return aToken.equals(fDOUBLE_QUOTE);
          }

          private static String flipDelimiters( String aCurrentDelims ) {
            String result = null;
            if ( aCurrentDelims.equals(fWHITESPACE_AND_QUOTES) ) {
              result = fQUOTES_ONLY;
            }
            else {
              result = fWHITESPACE_AND_QUOTES;
            }
            return result;
          }
        
      /**
        * Get a dynamic service name from the session ID.
       * @param theID - A session ID
       * @return - An substring of the session ID that is used for map services logs, and file names.
       */
      public static boolean isANumberInThisArray(int theID, int[] theIDList) {
         boolean whatYouWantToKnow = false;
         
         for (int i = 0; i < theIDList.length; i++) {
            if (theID == theIDList[i]) {
                return true;
            }
         }
         
         return whatYouWantToKnow;
      }
      /**
       * Test array contents
      * @param theID - A session ID
      * @return - An substring of the session ID that is used for map services logs, and file names.
      */
     public static boolean isTextInThisArray(String theText, String[] theArray) {
        boolean whatYouWantToKnow = false;
        
        for (int i = 0; i < theArray.length; i++) {
            if (theArray[i] != null && theArray[i] != null) {
                   if (theArray[i].contains(theText)) {
                       return true;
                   }
            }
        }
        
        return whatYouWantToKnow;
     }
      /**
        * Get a dynamic service name from the session ID.
       * @param theID - A session ID
       * @return - An substring of the session ID that is used for map services logs, and file names.
       */
      public static String getServiceName(String theID) {
         theID = theID.replace('%','z').substring(20, 26);
         return theID;
      }
      
      /** Get a <code>String</code> of form "R,G,B" from an instance of <code>Color</code>.
         * @param  parsed Color
         * @return Color as "200,200,200".
         */
        public static String colorToString(Color color) {
            return ("" + color.getRed() + "," + color.getGreen() + "," + color.getBlue());
        }
        
        /** Get a <code>Date</code> indication for DBConnection Pooling.
         * @param
         * @return Boolean, true = backup period
         */
        public static boolean isBackup() {
            boolean _isBackup = false;
            Calendar calendar;
            SimpleDateFormat _dayOfTheWeek = new SimpleDateFormat("EEE");
            SimpleDateFormat _hourOfTheDay = new SimpleDateFormat("k");
            return _isBackup;
        }
        
        
        /** Get an array of <code> Color </code> with given start Color and end Color
         * @param num number of break downs
         * @param start start Color
         * @param end  end Color
         * @return an array of <code> Color</code> objects
         */
        public static Color[] breakColors(Color start, Color end, int num) {
            Color[] colors = new Color[num];
            colors[0] = start;
            int sr = start.getRed();
            int sg = start.getGreen();
            int sb = start.getBlue();
            int er = end.getRed();
            int eg = end.getGreen();
            int eb = end.getBlue();
            for (int i = 1; i < num; i++){
                int r = sr + (int)((er-sr)* i / (num-1));
                int g = sg + (int)((eg-sg)* i / (num-1));
                int b = sb + (int)((eb-sb)* i / (num-1));
                colors[i] = new Color(r,g,b);
            }
            return colors;
        }
        /**
         * Break the list of colors into useable segments.
         * @return List of colors between startString and endString.
         */
        public static String[] breakColors(String startString, String endString, int num) {
            Color start = parseColor(startString);
            Color end = parseColor(endString);
            Color[] colors = breakColors(start,end,num);
            String[] colorStrings = new String[num];
            for (int i = 0; i < num; i++){
                colorStrings[i] = colorToString(colors[i]);
            }
            return colorStrings;
        }

        /** Validate if a text string is formatted well as an email
         *@param String emailA Address to check
         *@return boolean True or False
         */
        public static boolean isValidEmail(String emailA) {
            
          //Input the string for validation
          String email = "xyz@hotmail.com";

          //Set the email pattern string
          Pattern p = Pattern.compile(".+@.+\\.[a-z]+");

          //Match the given string with the pattern
          Matcher m = p.matcher(email);

          //check whether match is found 
          boolean matchFound = m.matches();

          if (matchFound)
            return true;
          else
            return false;

        }
        
        /**
         * Split a string into a String array EX "Boston roads" = [0] Boston
         *                                                        [1] Roads
         *
         */
        public static String[] splitString(String entry) {
            String cleanEntries = entry.trim();
            String[] splitStrings = null;
            splitStrings = cleanEntries.split("\\s+"); // Handles double spaces *again

            return splitStrings;
        }
        
        /**
         * Get the number of unique Data Publishers from an HGL search result bean
         * This is assuming that the results (myRes) come back sorted by Publication ID
         */
        public static int getNumUnique(hglSearchResultBean[] myRes, String _hits) {

            int numUnique = 1;
            int holder1 = 0;
            int holder2 = 0;
            if (myRes[0] != null) {
                holder1 = myRes[0].getPublication_id();
            } else {
                System.out.println("[WARNING] HGLUtilities.java:882 -- myRes[0].getPublication_id() was null");
            }
            
            for (int i = 0; i < Integer.parseInt(_hits);i++) {
            //for (int i = 0; i < myRes.length;i++) {
                if (myRes[i] != null) {
                    if (myRes[i].getDescription() != null) {
                    holder2 = myRes[i].getPublication_id();
                        if ( holder1 != holder2) {
                            holder1 = holder2;
                            numUnique++;
                        }
                    }
                }
            }        

            return numUnique;
        }

        /**
         * For some reason a Integer.parseInt is not working in my JSP
         *
         */
        public static int string2Int(String _hits) {
            return Integer.parseInt(_hits);
        }    
        
        public static void setClassBreakDown(double[] values, int method, int precision, String[] lower, String[] upper){
            int classes = lower.length;
            java.util.Arrays.sort(values);
            double base = Math.pow(10,precision);
            if(method == 0) {  // Equal Interval
                double min = values[0];
                double incre = (values[values.length-1]-min) / classes;
                for (int i = 0; i < classes; i++){
                    double low = (double)((long)((min+ (incre * i))* base + 0.5))/base;
                    double upp = (double)((long)((min+ (incre * (i+1)))* base + 0.5))/base;
                    if (precision == 0) {
                        lower[i] = String.valueOf((long)low);
                        upper[i] = String.valueOf((long)upp);
                    } else {
                        lower[i] = String.valueOf(low);
                        upper[i] = String.valueOf(upp);
                    }
                }
            } else if(method == 1){  //  Quantile Interval
                double increrec=(double) values.length/classes;
                for (int i = 0; i < classes; i++){
                    int lowrec = Math.min((int)(increrec*i), values.length-1);
                    int upprec = Math.min((int)(increrec*(i+1)), values.length-1);
                    double low = (double)((long)(values[lowrec] * base + 0.5))/base;
                    double upp = (double)((long)(values[upprec] * base + 0.5))/base;
                    if (precision == 0) {
                        lower[i] = String.valueOf((long)low);
                        upper[i] = String.valueOf((long)upp);
                    } else {
                        lower[i] = String.valueOf(low);
                        upper[i] = String.valueOf(upp);
                    }
                }
            }
        }
        
        /**
         * Tool to make arribute values "safe".
         * <p>   &lt;,&gt;,',&quot;,&amp;.
         * @param value the String contains "unsafe" chars.
         * @return the new value String.
         */
        public static String escape(String value){
            StringBuffer buf=new StringBuffer(value.length());
            for (int i=0; i<value.length(); i++){
                char c=value.charAt(i);
                switch (c)  {
                    case '<':  buf.append("&lt;"); break;
                    case '>':  buf.append("&gt;"); break;
                    case '&':
                        if(value.startsWith("&lt;",i)|| value.startsWith("&gt;",i)||
                        value.startsWith("&amp;",i)||value.startsWith("&apos;",i)||
                        value.startsWith("&quot;",i)){
                            buf.append(c);
                        } else {
                            buf.append("&amp;");
                        }
                        break;
                    case '\'': buf.append("&apos;"); break;
                    case '"':  buf.append("&quot;"); break;
                    default:   buf.append(c); break;
                }
            }
            return buf.toString();
        }
        /**
         * Tools to change escaped &amp;amp;, &amp;lt, &amp;gt, &amp;apos;, ..back.
         * @param value the String contains "safe" chars.
         * @return the new value String.
         */
        public static String unescape(String value){
            StringBuffer buf=new StringBuffer(value.length());
            int i=0;
            while (i<value.length()){
                char c=value.charAt(i);
                if (c=='&'){
                    if(value.startsWith("&lt;",i)){
                        buf.append('<');
                        i+=4;
                    } else if (value.startsWith("&gt;",i)){
                        buf.append('>');
                        i+=4;
                    } else if (value.startsWith("&amp;",i)){
                        buf.append('&');
                        i+=5;
                    } else if (value.startsWith("&apos;",i)){
                        buf.append('\'');
                        i+=6;
                    } else if (value.startsWith("&quot;",i)){
                        buf.append('"');
                        i+=6;
                    } else {
                        buf.append(c);
                        i++;
                    }
                }    else {
                    buf.append(c);
                    i++;
                }
            }
            return buf.toString();
        }
        

      /**
       * Writes the supplied text 'fileText' to: "/usr/local/ArcGIS/dynamicAXL/DYN" + serviceName + ".axl"
       * This makes it easy for ArcIMS to find and use for any kind of map service.
       */
      public boolean writeDynamicAXLFile(String fileText, String serviceName) throws Exception {

        String fileName = "/usr/local/ArcGIS/dynamicAXL/DYN" + serviceName + ".axl";
        File aFile = new File(fileName);

          if (aFile.exists())
            aFile.delete();

        aFile.createNewFile();
        FileOutputStream file1 = new FileOutputStream(fileName, true);

          for ( int i = 0; i < fileText.length(); i++ )
             file1.write(fileText.charAt(i));

          file1.close();


        return true;
      }

      /**
       * Generic method for file writing to: "/usr/local/arcims-9.0/dynamicAXL/" + theFileName + ".axl".
       */
      public static int writeFile(String fileText, String theFileName) throws Exception {

        String fileName = "/home/hgl/prod/arcgis/DynamicFiles/" + theFileName + ".axl";
        FileWriter fileWriter = new FileWriter(fileName, true);
        fileWriter.write(fileText + "\n" );
        fileWriter.close();

        return 1;
      }
      
     /**
      * Write ArcIMS AXL file containing extract parameters to disk - for debugging.
      */
      public void writeEXTFile(String fileText, String serviceName) throws Exception {

        String fileName = "/usr/local/arcims-9.0/dynamicAXL/EXT" + serviceName + ".axl";
        File aFile = new File(fileName);

          if (aFile.exists())
            aFile.delete();

        aFile.createNewFile();
        FileOutputStream file1 = new FileOutputStream(fileName, true);

          for ( int i = 0; i < fileText.length(); i++ )
             file1.write(fileText.charAt(i));

          file1.close();

        //return true;
      } /* End */
      
        /**
         * Creates a file if one doesn't exist.
         *
         * @param filepath full path of file you are attempting to create
         * @return true if the file was successfully created, false otherwise
         * @throws IOException occurs if the file could specified by the
         *         could not be created
         */
        
        public static boolean createNonExistingFile(String filepath) throws IOException {
        File file = new File(filepath);
            
        try {
          // create an empty file
          return file.createNewFile();
        } catch (IOException ioe) {
          throw new IOException("IOException: Could not create atomic " +
                          "file: " + filepath +
                          ioe.getMessage());
        }
        }
        
        /**
         * Write a debug file to disk.
         */
        public int writeFile( String fileName, String destDir, String fileText, int overWrite ) throws Exception {

          //  overWrite = 0 do not
          //  overWrite = 1 overwrite
          int Msg = 0;
          
          //  0 = All OK
          //  1 = Did not want to overwrite but it exists
          //  2 = Directory did not exist
          //  3 = 
          
          File aFile = new File(destDir + "/" + fileName);
           
          if (aFile.exists() && overWrite == 0) 
              return 1;
          
          if (aFile.exists() && overWrite == 1) {
             aFile.delete();
             aFile.createNewFile();
          }
          
          FileOutputStream file1 = new FileOutputStream(fileName, true);
            
          for ( int i = 0; i < fileText.length(); i++ )
              file1.write(fileText.charAt(i));
            
          file1.close();
            
          return Msg;
        }
      
        /**
         * Write a debug file to disk.
         */
        public static int writeGenericFile( String fileName, String destDir, String fileText, int overWrite ) throws Exception {

          //  overWrite = 0 do not
          //  overWrite = 1 overwrite
          int Msg = 0;
          
          //  0 = All OK
          //  1 = Did not want to overwrite but it exists
          //  2 = Directory did not exist
          //  3 = 
          
          File aFile = new File(destDir + "/" + fileName);
           
          if (aFile.exists() && overWrite == 0) 
              return 1;
          
          if (aFile.exists() && overWrite == 1) {
             aFile.delete();
             aFile.createNewFile();
          }
          
          FileOutputStream file1 = new FileOutputStream(destDir + "/" + fileName, true);
            
          for ( int i = 0; i < fileText.length(); i++ )
              file1.write(fileText.charAt(i));
            
          file1.close();
            
          return Msg;
        }
        
        /**
         * Removes the directory if it doesn't contain any files.  Recurses
         * up the directory tree, checking to see if the parent directory is
         * now empty.  Requires a stop name - a directory name it will stop
         * while checking parent directories.  Typically this is "incoming".
         *
         * @param dir the directory which will be deleted if it is empty.  
         *            method will delete parent directories recursively if
         *            they become empty.
         * @throws IOException occurs if the files could not be deleted
         */
        
        public static void removeEmptyDirs(String dir, String stopDir)
            throws IOException
        {
            if (dir.equals(stopDir)) {
                // stop condition
                return;
            }

            // remove any empty directories we removed files from
            File deadDir = new File(dir);
            boolean empty = false;
            if (deadDir.exists() && deadDir.isDirectory()) {
                String files[] = deadDir.list();
                empty = true;
                if (files != null && files.length > 0) {
                    for (int i=0;i<files.length;i++) {
                        if (!files[i].equals(".") &&
                            !files[i].equals("..")) {
                            empty = false;
                            break;
                        }
                    }
                }
            }
            
            if (empty) {
                deadDir.delete();
                
                // recurse
                removeEmptyDirs(deadDir.getParentFile().getAbsolutePath(),stopDir);
            }
        }
        
        /**
         * Removes all the files in the specified directory and the directory itself.
         * this needs to be recursive
         *
         * @param dir the directory in which all the files and directories will be
         *              deleted. The directory itself will then be deleted.
         * @throws IOException occurs if the files could not be deleted
         */
        
        public static void removeFilesAndDir(String dir)    throws IOException {
            
            // removes all the files in the directory
            String[] fileList;
            File sourceDir = new File(dir);
            File file;
            
            // copy the files one by one to the destination area
            fileList = sourceDir.list();
            for (int i=0;i<fileList.length;i++) {
                file = new File(dir + File.separator + fileList[i]);
                //If this is a directory recurse
                if (file.isDirectory() == true) {
                    removeFilesAndDir(file.toString());
                }
                else {
                    removeFile(dir + File.separator + fileList[i]);
                }
            }
            //now that the directory is empty delete it.
            sourceDir.delete();
        }

        /**
         * Removes the specified file.
         *
         * @param filepath the full file path of the file that will
         *                   be deleted
         * @throws IOException occurs if the file could not be deleted
         */
        public static void removeFile(String filepath) throws IOException {
            
            File deleteFile = new File(filepath);
            
            if (deleteFile.delete() == false) {
                    throw new IOException("File could not be deleted: " + filepath);
            }
        }
        
        /**
         * Lets you know if a file already exists.
         *
         * @param filepath the full file path of the file that will
         *                   be tested
         * @throws IOException occurs if the file could not be tested
        */
        public static boolean fileExists(String filepath) throws IOException {
                        
            File deleteFile = new File(filepath);
            
            if (deleteFile.exists()) {
                return true;
            } else {
                return false;
            }
        }
        
        
        /**
         * Removes all the files in the specified directory.
         *
         * @param dir the directory in which all the files will be
         *              deleted
         * @throws IOException occurs if the files could not be deleted
        */
        public static void removeFiles(String dir) throws IOException {
            
            // removes all the files in the directory
            String[] fileList;
            File sourceDir = new File(dir);
            File file;

            // copy the files one by one to the destination area
            fileList = sourceDir.list();
            for (int i=0;i<fileList.length;i++) {
                    file = new File(dir + File.separator + fileList[i]);
                    if (file.isDirectory() == false) {
                            removeFile(dir + File.separator + fileList[i]);
                    }
            }
        }

        public static String getDate() {
            SimpleDateFormat _dayOfTheWeek = new SimpleDateFormat("EEE");
            SimpleDateFormat _hourOfTheDay = new SimpleDateFormat("k");
            return "S";
        }
       
        /**
         * Make a directory.
         * @param dir - The directory you want to create - full path and name are required.
         *            - Most often used to create a new directory in /mnt/pratchett/hgl_asynch/prod
         *              to handle placing raster data clips and copies for downloads.
         */
        public static boolean mkDir(String dir) {
            
          String cpCommand = "chmod 777 " + dir;
          File aFile = new File(dir);
          
          if (aFile.exists()) {
            return false;
          } else {
            aFile.mkdir();
            Runtime runtime = Runtime.getRuntime();
            
                try {
                    Process proc = runtime.exec(cpCommand);
                    try {
                        if (proc.waitFor() != 0) {
                            return true;
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } catch (Exception prc) {
                    prc.printStackTrace();
                    return true;
                }
          }
          return true;
          
        }

        /**
         * See if a map service exists.
         *@param ConnectionProxy mcp = An ArcIMS connection proxy. In HGL it's set up
         * in an initialization servlet and placed into the applications context.
         *@return TRUE or FALSE
         */
        public static boolean doesMapServiceExist(ConnectionProxy mcp, String mapServiceName) throws IOException {
            boolean answer = false;
            
            try {

                ServiceCollection service_collection = ServiceCollection.getServices(mcp);
                Service[] services = new Service[service_collection.size()];

                for (int i=0;i<service_collection.size();i++){
                  Service aservice = service_collection.getService(i);
                  services[i] = aservice;
                    if (aservice.getName().equalsIgnoreCase(mapServiceName)) {
                      answer = true;
                      break;
                    }
                }

            } catch (Exception e) {
              e.printStackTrace();
            }
            
            return answer;
        }
        
        /**
         * Write a debug file to disk. (/home/hgl/prod/arcgis/DynamicFiles/logfiles/search_tracker.log)
         */
        public static void writeDebugLogFile( String fileText, int overWrite ) throws Exception {

            String fileName = "/home/hgl/prod/arcgis/DynamicFiles/logfiles/search_tracker.log";
            File aFile = new File(fileName);

            if (aFile.exists() && overWrite == 1) {
                aFile.delete();
                aFile.createNewFile();
            }
            FileOutputStream file1 = new FileOutputStream(fileName, true);

            for ( int i = 0; i < fileText.length(); i++ )
                file1.write(fileText.charAt(i));

            file1.close();

        }
        
        /**
         * Get a list of all the ArcIMS services running on localhost
         *@param ConnectionProxy mcp = An ArcIMS connection proxy. In HGL it's set up
         * in an initialization servlet and placed into the applications context.
         *@return String[] of services.
         */
        public static String[] getListOfArcIMSServices(ConnectionProxy mcp) throws IOException {
            
            String[] listOfServices = new String[500];
            int reaction = 450;

            try {

                reaction = mcp.ping(false);

                ServiceCollection service_collection = ServiceCollection.getServices(mcp);
                Service[] services = new Service[service_collection.size()];

                for (int i=0;i<service_collection.size();i++){
                  Service aservice = service_collection.getService(i);
                  services[i] = aservice;
                  listOfServices[i] = aservice.getName();
                }

            } catch (Exception e) {
              e.printStackTrace();
            }
            
            return listOfServices;
        }

        /** Enable WMS for an ArcIMS map service. Send the command to the /wmsconnector context
         *@param ServiceName The name of the map service to enable WMS for
         *@retun int status of the WMS
         */
        public static int enableWMS(String serviceName) throws IOException {

            String s = "";

            String theHost = java.net.InetAddress.getLocalHost().getHostName();

        try {
            URL u;
                u = new URL("http://"+theHost+":8080/wmsconnector/admin/mylogin2.jsp?ServiceName="+serviceName);
          
            // Open the connection and prepare to POST
            URLConnection uc = u.openConnection();
            uc.setDoOutput(true);
            uc.setDoInput(true);
            uc.setAllowUserInteraction(false);

            DataOutputStream dstream = new DataOutputStream(uc.getOutputStream());
          
            // The POST line
            dstream.writeBytes(s);
            dstream.close();

            // Read Response 
            InputStream in = uc.getInputStream();
            int x;
            while ( (x = in.read()) != -1) {
                    System.out.write(x);
            }
            in.close();

            BufferedReader r = new BufferedReader(new InputStreamReader(in));
            StringBuffer buf = new StringBuffer();
            String line;
            while ((line = r.readLine())!=null) {
                    buf.append(line); 
            }  

        } catch (IOException e) { 
            e.printStackTrace();    // should do real exception handling
        }

            return 1;
        }

        /** Disable WMS for an ArcIMS map service the kind way. Send the command to the /wmsconnector context
         *@param ServiceName The name of the map service to enable WMS for
         *@retun int status of the WMS
         */
        public static int disableWMS(String serviceName) throws IOException {

            String s = "";

            String theHost = java.net.InetAddress.getLocalHost().getHostName();
            
        try {
            URL u;
                u = new URL("http://"+theHost+":8080/wmsconnector/admin/mylogin3.jsp?ServiceName="+serviceName);
          
            // Open the connection and prepare to POST
            URLConnection uc = u.openConnection();
            uc.setDoOutput(true);
            uc.setDoInput(true);
            uc.setAllowUserInteraction(false);

            DataOutputStream dstream = new DataOutputStream(uc.getOutputStream());
          
            // The POST line
            dstream.writeBytes(s);
            dstream.close();

            // Read Response 
            InputStream in = uc.getInputStream();
            int x;
            while ( (x = in.read()) != -1) {
                    System.out.write(x);
            }
            in.close();

            BufferedReader r = new BufferedReader(new InputStreamReader(in));
            StringBuffer buf = new StringBuffer();
            String line;
            while ((line = r.readLine())!=null) {
                    buf.append(line); 
            }  

        } catch (IOException e) { 
            e.printStackTrace();    // should do real exception handling
        }

            return 1;
        }

        /** Get all of the DRS files with path names that are related to this ID
         *@param int DRS base ID of the SDE layer
         *@return String[] All the associated files (.tfw, .jpeg etc.)
         */
        public static String[] getDRSPathAndName( int drsID ) throws IOException {

            String[] drsFiles = new String[10];
            int count = 0;
            
            java.sql.ResultSet _resultSet = null;
            java.sql.Connection _con = null;

            String theQuery = "select d.object_id, d.filepath, o.mimetype, o.supplied_name, d.access_flag,t.descriptor_type " +
                              "from repository.drs_objects d,repository.owner_access_to_objects o, repository.text_metadata t " +
                              "where o.object_id = d.object_id and t.object_id (+) = d.object_id and d.object_id in " +
                              "((select r.b_object_id from repository.relationship_map r where r.rtype='IS_WORLD_FILE_OF' and r.a_object_id=" + drsID + ") union " +
                              "(select r.a_object_id from repository.relationship_map r  where r.rtype='IS_WORLD_FILE_OF' and r.b_object_id=" + drsID + ") union " +
                              "(select d.object_id from repository.drs_objects d where d.object_id = " + drsID + ")) ORDER BY d.OBJECT_ID";

            String jdbcConnect = "jdbc:oracle:thin:@drsdb.hul.harvard.edu:8003:DRSPROD";
            String user = "repository";
            String pass = "mitchell25";
            String driver = "oracle.jdbc.OracleDriver";

                try {
                    Class.forName(driver).newInstance();
                    _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                    Statement stmnt = _con.createStatement();
                    ResultSet rs = stmnt.executeQuery(theQuery);

                    while (rs.next()) {
                        if (!rs.getString("OBJECT_ID").trim().equalsIgnoreCase("99")) {
                           drsFiles[count] = rs.getString("FILEPATH");
                           count++;
                       }
                    }

                    rs.close();
                    stmnt.close();
                    _con.close();

                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            
            return drsFiles;
            
        }
                
        /** Get the base NAME (SUPPLIED_NAME) from the DRS
         *@param String DRSID (change to int)
         *@return int The base ID for that layer - base the DRS relationship query on this
         */
        public static String getDRSBaseNameFromID(String id) throws IOException {
            
            int drsID = Integer.parseInt(id);
            String suppName = "none";
            int count = 0;
            
            java.sql.ResultSet _resultSet = null;
            java.sql.Connection _con = null;

            String theQuery = "select d.object_id, d.filepath, o.mimetype, o.supplied_name, d.access_flag,t.descriptor_type " +
                              "from repository.drs_objects d,repository.owner_access_to_objects o, repository.text_metadata t " +
                              "where o.object_id = d.object_id and t.object_id (+) = d.object_id and d.object_id in " +
                              "((select r.b_object_id from repository.relationship_map r where r.rtype='IS_WORLD_FILE_OF' and r.a_object_id=" + drsID + ") union " +
                              "(select r.a_object_id from repository.relationship_map r  where r.rtype='IS_WORLD_FILE_OF' and r.b_object_id=" + drsID + ") union " +
                              "(select d.object_id from repository.drs_objects d where d.object_id = " + drsID + ")) ORDER BY d.OBJECT_ID";

            String jdbcConnect = "jdbc:oracle:thin:@drsdb.hul.harvard.edu:8003:DRSPROD";
            String user = "repository";
            String pass = "mitchell25";
            String driver = "oracle.jdbc.OracleDriver";

                try {
                    Class.forName(driver).newInstance();
                    _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                    Statement stmnt = _con.createStatement();
                    ResultSet rs = stmnt.executeQuery(theQuery);

                    while (rs.next()) {
                        suppName = rs.getString("SUPPLIED_NAME");
                    }

                    rs.close();
                    stmnt.close();
                    _con.close();

                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            
            return suppName;
            
        }
        /** Get the base ID of an SDE image that's in the DRS. The base ID is the 
         * basis for a DRS query that brings back all of the associated files, such
         * as the world file.
         *@param String Layer name to look up
         *@param int operation -- 1 = get the DRS ID, any other number = get the record count
         *@return int The base ID for that layer - base the DRS relationship query on this
         */
        public static int getDRSBaseID(String layerName,
                                       int operation) throws IOException {
            
            int theID = 0;
            int counter = 0;
            
            String owner = "SDE";
            java.sql.ResultSet _resultSet = null;
            java.sql.Connection _con = null;

            String theQuery = "SELECT DRS_ID FROM GLOBAL_RASTER WHERE UPPER(TRIM(HGL_TABLE_NAME)) = '" + layerName.toUpperCase().trim() + "' ORDER BY DRS_ID DESC";

                try {
                    Class.forName(driver).newInstance();
                    _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                    Statement stmnt = _con.createStatement();
                    ResultSet rs = stmnt.executeQuery(theQuery);

                    while (rs.next()) {
                      theID = rs.getInt("DRS_ID");
                      counter++;
                    }

                    rs.close();
                    stmnt.close();
                    _con.close();

                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            /* Send back the result */
            if (operation == 1)
              return theID;
            else 
              return counter;
            
        }
        
        /** Create an ArcIMS map service dynamically
         *@param ConnectionProxy mcp = An ArcIMS connection proxy. In HGL it's set up
         * in an initialization servlet and placed into the applications context.
         *@return 0 = no service created and started, 1 = all went OK
         */
        public static int createArcIMSMapService(ConnectionProxy mcp, String serviceName, String AXLFile, int serviceType) throws IOException {

            int status = 0;
            String SERVICE_PATH = AXLFile;
            String SERVICE_NAME = serviceName;
            String OUTPUT_PATH = "/home/hgl/prod/arcgis/output";
            String OUTPUT_URL = "http://localhost/output";

            java.io.FileInputStream myservice_fis = new java.io.FileInputStream(SERVICE_PATH);
            Service myservice = new Service();
            myservice.setConfigFile(SERVICE_PATH);
            myservice.setConfigContents(myservice_fis, false);
            myservice.setName(SERVICE_NAME);
            
            if (serviceType == 1 ) {
                myservice.setVirtualServer("ImageServer1", "ImageServer", "");
                myservice.setImageType(Service.IMAGE_JPG);
                myservice.setOutputDir(OUTPUT_PATH);
                myservice.setOutputURL(OUTPUT_URL);
                myservice.setPixelCount(4000000);
                myservice.setOutputCleanup(10);
            } else if (serviceType == 2 ) {
                myservice.setVirtualServer("ExtractServer1", "ExtractServer", "");
                myservice.setImageType(Service.IMAGE_JPG);
                myservice.setOutputDir(OUTPUT_PATH);
                myservice.setOutputURL(OUTPUT_URL);
                myservice.setPixelCount(4000000);
                myservice.setOutputCleanup(120);
            }

            try {
                boolean myservice_add = myservice.addService(mcp);
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                boolean myservice_start = myservice.startService(mcp);
                    if (myservice_start) {
                        status = 1;
                    }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return status;
        }
        
        /** Delete an ArcIMS map service
         *@param ConnectionProxy mcp = An ArcIMS connection proxy. In HGL it's set up
         * in an initialization servlet and placed into the applications context.
         * @param String serviceName The name of the IMS service to remove
         *@return 0 = status of service removal, 1 = all went OK
         */
        public static int deleteArcIMSMapService(ConnectionProxy mcp, String serviceName) throws IOException {

            int status = 0;
            String SERVICE_PATH = "/home/hgl/prod/arcgis/AXL/world.axl";
            String SERVICE_NAME = serviceName;
            String OUTPUT_PATH = "/home/hgl/prod/arcgis/output";
            String OUTPUT_URL = "http://localhost/output";

            Service myservice = new Service();
            myservice.setName(SERVICE_NAME);
            myservice.setVirtualServer("ImageServer1", "ImageServer", "");

            try {
                boolean myservice_delete = myservice.removeService(mcp);
                    if ( myservice_delete) {
                        status = 1;
                    }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return status;
        }

        /** Get the SDE layer extent for layer x
         * This has got to be added to the Map Extent Cookie
         *@param String Layer name to look up
         *@return double[] The map extent
         */
        public static double[] getLayerCenterExtent(int layerID) throws IOException {
            

            String projString = "none";
            int projCode = 0;
            
            /* You need to get the native coordinate system and then transform those coordinates
             * to long/lat.
             */
            // get the projection string for the layer
            projString = HGLUtilities.getArcIMSProjectionString(layerID);
            
            // get the projection ID
            projCode = HGLUtilities.getArcIMSProjectionID(projString);
                    
            // ---------------------------------------------------
            
            int theID = 0;
            int counter = 0;
            double[] retCoords = new double[4];
            String[] transformedCoords = new String[4];
            String[] tempCoords = new String[4];
            double cX = 0;
            double cY = 0;
            double zoom = 4;
            
            java.sql.Connection _con = null;

            String theQuery = "SELECT MINX, MAXX, MINY, MAXY FROM LAYERS WHERE LAYER_ID = " + layerID;
            
                try {
                    Class.forName(driver).newInstance();
                    _con = java.sql.DriverManager.getConnection(jdbcConnect, user, pass);

                    Statement stmnt = _con.createStatement();
                    ResultSet rs = stmnt.executeQuery(theQuery);
                    
                    if (rs.next()) {                    
                      retCoords[0] = rs.getDouble("MINX");
                      retCoords[1] = rs.getDouble("MAXX");
                      retCoords[2] = rs.getDouble("MINY");
                      retCoords[3] = rs.getDouble("MAXY");
                    } else {
                        retCoords[0] = 9999;
                        retCoords[1] = 9999;
                        retCoords[2] = 9999;
                        retCoords[3] = 9999;          
                    }

                    rs.close();
                    stmnt.close();
                    _con.close();

                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
      
                if (projCode != 4326) {
                    tempCoords[0] = Double.toString(retCoords[0]);
                    tempCoords[1] = Double.toString(retCoords[1]);
                    tempCoords[2] = Double.toString(retCoords[2]);
                    tempCoords[3] = Double.toString(retCoords[3]);

                    // returns String[]
                    transformedCoords = getTransformCoordinates(tempCoords, projCode, "4326");
                    
                    retCoords[0] = Double.parseDouble(transformedCoords[0]);
                    retCoords[1] = Double.parseDouble(transformedCoords[2]);
                    retCoords[2] = Double.parseDouble(transformedCoords[1]);
                    retCoords[3] = Double.parseDouble(transformedCoords[3]);
                    
                    //Translated 4269 to 4326.
                    //retCoords[0] -73.4974566765616
                    //retCoords[1] 41.2495548116805
                    //retCoords[2] -69.9659386357604
                    //retCoords[3] 42.8863812450794
                    
                    try {
                        writeDebugLogFile("Translated "+ projCode+" to 4326.\n",0);
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                        
                cX = (retCoords[0] + retCoords[2]) / 2;
                cY = (retCoords[1] + retCoords[3]) / 2;
                
                zoom = ((retCoords[0] - retCoords[2]) * (retCoords[1] - retCoords[3]));
                if (zoom < 50) {
                    zoom = 6;
                } else if (zoom >= 50 && zoom < 600) {
                    zoom = 4;
                } else {
                    zoom = 1;
                }
                
                double rets[] = new double[3];
                rets[0] = cX;
                rets[1] = cY;
                rets[2] = zoom;
                
                return rets;
            
        }
        
        /**
         * Transform coordinates using the ArcSDE API
         * @param x
         * @param y
         * @return
         */
        public static double[] getTransformFrom4326(int toCoordSys, double x, double y) throws IOException {
        
            PeCSTransformations tr = null;
            PeProjectedCS a = null;
            try {
                // Specify the EPSG code to convert to
                PeObject peobject =  PeFactory.factory(toCoordSys);
                a = new PeProjectedCS(peobject.toString());
            } catch (PeProjectionException e) {
                e.printStackTrace();
            }
            
             // Here are my lat/long coordinates
            double[] array = new double[2];
            array[0] = x;
            array[1] = y;
            
            int result = 0;
      
            // Replace the contents of array[] with projected coordinates
            try {
                result = tr.geogToProj(a,1,array);
            } catch (PeProjectionException e) {
                e.printStackTrace();
            }
            return array;
        }
        
        /**
         * Transform coordinates Vvia ArcIMS
         * @param theCoords - int[] of coordinates from the map frame that you want to translate to the layer's coordinate system
         * @param fromCoordSys - The coordinate system to translate from, usually the main HGL Mao service
         * @param toCoordSys - The coordinate system ID of the layer
         */
        public static String[] getTransformCoordinates(
                                String[] theCoords, 
                                int fromCoordSys,
                                String toCoordSys) throws IOException {

        /**
         * Set the AXL REQUEST - PROJECT REQUEST Good from IMS 9.0 SP2 +
         */
        String AXL = "none";
        String rAXL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 
                        "<ARCXML version=\"1.1\">" +
                          "<REQUEST>" + 
                            "<GET_PROJECT envelope=\"true\">" +
                              "<FROMCOORDSYS id=\""+fromCoordSys+"\"/>" + // Usually 4326 -- geographic from HGLMap service
                              "<TOCOORDSYS id=\""+toCoordSys+"\"/>" +  //-- 53030
                              "<ENVELOPE minx=\""+ theCoords[0] +"\" miny=\"" + theCoords[2] + "\" maxx=\"" + theCoords[1] + "\" maxy=\"" + theCoords[3] + "\"/>" +
                           "</GET_PROJECT>" +
                          "</REQUEST>" +
                        "</ARCXML>";

        ConnectionProxy adminTCP = new ConnectionProxy();
        adminTCP.setConnectionType(ConnectionProxy.HTTP);
        adminTCP.setService("HGLMap&CustomService=Query");
        adminTCP.setUrl(new java.net.URL("http://hgl.harvard.edu:8080"));
                   
            try {
                AXL = adminTCP.send(rAXL).trim();
        } catch (Exception ex) {
            ex.printStackTrace ();
        }
        
         String[] transformedCoords = new String[4];
         
         /* Did any valid AXL return? */
         if (AXL.indexOf("ENVELOPE") > 0 ) {
        
            // XML org.jdom.Document Builder in JDOM is used for creating a JDOM Document
            DOMBuilder jdomBuilder = new DOMBuilder();
            SAXBuilder saxBuilder = new SAXBuilder();

                try {
                    org.jdom.Document xmlResponseJDOM = saxBuilder.build(new StringReader(AXL));
                    // Get root Element
                    org.jdom.Element eResponseRoot =  xmlResponseJDOM.getRootElement();
                    // Retrieve ENVELOP Element coordinates
                    transformedCoords[0] = eResponseRoot.getChild("RESPONSE")
                                                    .getChild("PROJECT")
                                                    .getChild("ENVELOPE").getAttributeValue("minx");                      
                    transformedCoords[1] = eResponseRoot.getChild("RESPONSE")
                                                    .getChild("PROJECT")
                                                    .getChild("ENVELOPE").getAttributeValue("maxx");
                    transformedCoords[2] = eResponseRoot.getChild("RESPONSE")
                                                    .getChild("PROJECT")
                                                    .getChild("ENVELOPE").getAttributeValue("miny");  
                    transformedCoords[3] = eResponseRoot.getChild("RESPONSE")
                                                    .getChild("PROJECT")
                                                    .getChild("ENVELOPE").getAttributeValue("maxy");        
                } catch (Exception c) {
                    c.printStackTrace();
                }
         } else {
             transformedCoords[0] = "0";
             transformedCoords[1] = "0";
             transformedCoords[2] = "0";
             transformedCoords[3] = "0";
         }
         return transformedCoords;
        }
        
        /**
         * Move a file on the file system
         * @param fromFile - Name of file to copy
         * @param fromPath = Path where the file is located
         * @param toFile - File name to copy to
         * @param toPath = Place to put the file
         */
        public static boolean moveFile( String fromFilePath,
                                        String toPath ) {

           int start = fromFilePath.lastIndexOf("/");
           String toFile = fromFilePath.substring(start);
           
            try {
               if (HGLUtilities.fileExists(toPath+"/"+toFile))
                   HGLUtilities.removeFile(toPath+"/"+toFile);
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }
            
            String cpCommand = "cp "+fromFilePath+" "+toPath+"/"+toFile;
            Runtime runtime = Runtime.getRuntime();

            try {
                Process proc = runtime.exec(cpCommand);
                try {
                    if (proc.waitFor() != 0) {
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (Exception prc) {
                prc.printStackTrace();
            }
            
            
            // 3. Validate that the raster was clipped and send + or - back
            File aFile = new File(toPath+"/"+toFile);
            if (aFile.exists()) 
               return true;
             else
               return false;
        }

        /**
         * Move a file on the file system
         * @param fromFile - Name of file to copy
         * @param fromPath = Path where the file is located
         * @param toFile - File name to copy to
         * @param toPath = Place to put the file
         */
        public static boolean moveFile(String fromFile,
                                        String fromPath,
                                        String toFile,
                                        String toPath ) {
            try {
               if (HGLUtilities.fileExists(toPath+"/"+toFile))
                   HGLUtilities.removeFile(toPath+"/"+toFile);
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }

            String cpCommand = "cp "+fromPath+"/"+fromFile+" "+toPath+"/"+toFile;
            Runtime runtime = Runtime.getRuntime();

            try {
                Process proc = runtime.exec(cpCommand);
            
                try {
                    if (proc.waitFor() != 0) {
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (Exception prc) {
                prc.printStackTrace();
            }

            
            // 3. Validate that the raster was clipped and send + or - back
            File aFile = new File(toPath+"/"+toFile);
            if (aFile.exists()) 
               return true;
             else
               return false;
        }
        
        /**
         * Clip a raster from HGL SDE PROD
         * @param layerName - The ArcSDE raster layer name.
         * @param coords - coordinates in the correct coordinate system
         * @param outName - The name of the output image
         * @param rType - -l parameter  USER.NAME,RASTER < RASTER | IMAGE >
         */
        public static boolean clipSDERasterLayer( String owner,      // Table owner
                                                  String layerName,  // SDE raster layer name (SDE.NAME)
                                                  String[] coords,   // xy pair to use for clipping
                                                                     //    minX, maxX, minY, maxY
                                                  String outName,    // Name of the output file
                                                  String rType       // IMAGE or RASTER -l name,RASTER
                                                 ) {
            //boolean wasMade = false;                                                 
            //#. Get the directory
            GregorianCalendar calendar = new GregorianCalendar();
            String today = (calendar.get(calendar.MONTH)+1) + "-" + calendar.get(calendar.DAY_OF_MONTH) + "-" + calendar.get(calendar.YEAR);

            // # If the files already exists you should remove them
            String destDir = "/mnt/pratchett/hgl_asynch/prod/";
            
            try {
                if (HGLUtilities.fileExists(destDir+outName+".tif"))
                   HGLUtilities.removeFile(destDir+outName+".tif");
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }
            
            String clipCommand = "sderaster -o export -l "+owner+"."+layerName+","+rType.toUpperCase().trim()+" -v 1 -f " + destDir+outName.trim()+".tif" + 
            " -e " + coords[0] + "," + coords[2]+ "," + coords[1] + "," + coords[3] + " -i sde:oracle11g -u "+user+" -p "+pass+"@hglprd";

            try {
                writeDebugLogFile(clipCommand,0);
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }
            
            // 2. Run the command via ssh
            try {
                Connection conn = new Connection(shostname);
                conn.connect();
                boolean isAuthenticated = conn.authenticateWithPassword(susername, spassword);

                if (isAuthenticated == false)
                    throw new IOException("Authentication failed.");

                Session sess = conn.openSession();
                sess.execCommand("source changeHGLPRD_csh && "+ clipCommand + "  && chmod 777 " + destDir+outName.trim()+".tif");
                InputStream stdout = new StreamGobbler(sess.getStdout());
                BufferedReader br = new BufferedReader(new InputStreamReader(stdout));

                while (true) {
                    String line = br.readLine();
                    if (line == null)
                        break;
                    System.out.println(line);
                }

                sess.close();
                conn.close();

            } catch (IOException e) {
                e.printStackTrace(System.err);
                System.exit(2);
            }

            String cpCommand = "cp /mnt/pratchett/hgl_asynch/prod/" + outName.trim()+".tif" + " /home/hgl/prod/arcgis/output/" + outName.trim()+".tif";
            String cpCommand2 = "cp /mnt/pratchett/hgl_asynch/prod/" + outName.trim()+".tfw" + " /home/hgl/prod/arcgis/output/" + outName.trim()+".tfw";
            String rmCommand = "rm /mnt/pratchett/hgl_asynch/prod/" + outName.trim()+".tif";
            String rmCommand2 = "rm /mnt/pratchett/hgl_asynch/prod/" + outName.trim()+".tfw";
            Runtime runtime = Runtime.getRuntime();
            
            try {
                Process proc = runtime.exec(cpCommand);
                try {
                    if (proc.waitFor() != 0) {
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (Exception prc) {
                prc.printStackTrace();
            }
            
            
            /*
            try {
                Process proc = runtime.exec(cpCommand2);
                try {
                    if (proc.waitFor() != 0) {
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (Exception prc) {
                prc.printStackTrace();
            }
            */
            // The following loop was used for debugging but I like to see the results in catalina.out 
            // so I am keeping it.
            //try {
            //   if (HGLUtilities.fileExists(destDir+outName.trim()+".tif"))
            //       System.out.println("The TIF file exists!");
               //if (HGLUtilities.fileExists(destDir+outName.trim()+".tfw"))
               //    System.out.println("The TFW file exists!");
            //} catch (Exception noGo) {
            //   noGo.printStackTrace();
            //}
            // 3. Validate that the raster was clipped and send + or - back
            File aFile = new File(destDir+outName.trim()+".tif");
            if (aFile.exists()) 
               return true;
             else
               return false;
          
            }
        
        /**
         * Write a log message for the thread since it cannot access sys logs
         */
        public static void printStatusQueryMessage(String message) {
            try {
                writeDebugLogFile(message,0);
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }
        }
        
        /**
         * Clip a vector data set from HGL without using a map service
         * @param layerName - The ArcSDE raster layer name.
         * @param coords - coordinates in the correct coordinate system
         * @param outName - The name of the output image
         * @param rType - -l parameter  USER.NAME,RASTER < RASTER | IMAGE >
         */
        public static boolean clipSDEVectorLayer( String owner,      // Table owner
                                                  String layerName,  // SDE raster layer name (SDE.NAME)
                                                  double[] coords,   // xy pair to use for clipping
                                                                     //    minX, maxX, minY, maxY
                                                  String outName,    // Name of the output file
                                                  int clip           // 1 = clip, 0 = no clip
                                                 ) {

            GregorianCalendar calendar = new GregorianCalendar();
            String today = (calendar.get(calendar.MONTH)+1) + "-" + calendar.get(calendar.DAY_OF_MONTH) + "-" + calendar.get(calendar.YEAR);

            String destDir = "/mnt/pratchett/hgl_asynch/prod/";
           
            try {
               if (HGLUtilities.fileExists(destDir+outName.trim()+".shp"))
                   HGLUtilities.removeFile(destDir+outName.trim()+".shp");
               if (HGLUtilities.fileExists(destDir+outName.trim()+".shx"))
                   HGLUtilities.removeFile(destDir+outName.trim()+".shx");
               if (HGLUtilities.fileExists(destDir+outName.trim()+".prj"))
                   HGLUtilities.removeFile(destDir+outName.trim()+".prj");
               if (HGLUtilities.fileExists(destDir+outName.trim()+".dbf"))
                   HGLUtilities.removeFile(destDir+outName.trim()+".dbf");
               if (HGLUtilities.fileExists(destDir+outName.trim()+".map"))
                   HGLUtilities.removeFile(destDir+outName.trim()+".map");
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }
            
            // The SE_TOOLKIT command to run
            String clipCommand = "sdequery -l ";

            if (clip == 1) {
                //clipCommand = clipCommand + owner+"."+layerName+",shape -F1 SM_II_OR_ET:T:box,"+coords[0]+","+coords[2]+","+coords[1]+","+coords[3] + " -d "+destDir+outName.toLowerCase().trim()+".shp -i sde:oracle11g -u user -p password@hglprd";
                clipCommand = clipCommand + owner+"."+layerName+",shape -E "+coords[0]+","+coords[2]+","+coords[1]+","+coords[3] + " -d "+destDir+outName.toLowerCase().trim()+".shp -i sde:oracle11g -u "+user+" -p "+password+"@hglprd";
            } else {
                clipCommand = clipCommand + owner+"."+layerName+",shape -d "+destDir+outName.toLowerCase().trim()+".shp -i sde:oracle11g -u "+user+" -p "+password+"@hglprd";
            }
            
            try {
                writeDebugLogFile(clipCommand+"\n\n",0);
            } catch (Exception noGo) {
               noGo.printStackTrace();
            }
            
            // 2. Run the command via ssh
            try {
                Connection conn = new Connection(shostname);
                conn.connect();
                boolean isAuthenticated = conn.authenticateWithPassword(susername, spassword);

                if (isAuthenticated == false)
                    throw new IOException("Authentication failed.");

                Session sess = conn.openSession();
                            sess.execCommand("source changeHGLPRD_csh && "+ clipCommand + "  && chmod 777 " + destDir+outName.trim()+".*");
                InputStream stdout = new StreamGobbler(sess.getStdout());
                BufferedReader br = new BufferedReader(new InputStreamReader(stdout));

                while (true) {
                    String line = br.readLine();
                    if (line == null)
                        break;
                    System.out.println(line);
                }

                sess.close();
                conn.close();

            } catch (IOException e) {
                e.printStackTrace(System.err);
                System.exit(2);
            }

            // Validate that the shape file exists and that it has size > 0 bytes (1024 bytes = 1 KB)
            File aFile = new File(destDir+outName.toLowerCase().trim()+".shp");
            if (aFile.exists() && aFile.length() > 0) 
               return true;
             else
               return false;
          
        }


        /**
         * Calculate the size of a clipped image
         * @param layerID - ArcSDE layer ID for image
         * @param host - machine to connect to
         * @param user
         * @param pass
         *  This method assumes complete contains: B is wholely contained in A
         *      - so, it needs an overlap function getPercentOverlap
         */
        public static int calculateImageSize(int layerID) {
            return 28;
            /*
            SELECT RASTERCOLUMN_ID FROM RASTER_COLUMNS WHERE TABLE_NAME = 'MODIS'
            SELECT BAND_WIDTH * BAND_HEIGHT AS ORIG_PIXELS, ROUND(EMINX), ROUND(EMINY), ROUND(EMAXX), ROUND(EMAXY) FROM SDE_BND_(RASTERCOLUMNS_ID)

            Get raster # from raster columns
            get eminX, eminY etc from SDE_BLK_#
                - calc total area
            get width and height of pixels
                - calc total size
            send map frame through COORDSYS converter (if not 4326 (current map extent #)
            get new minX, maxX back
                calculate new area
            divide new area by original area (naOA)
            multiple original megs by naOA
            determine if file size is too big
            * might have to add all the file sizes together first (several USGS maps)
            */
        }
        
        
        /**
         * Change file/folder permissions - hard coded for security
         * @param fileName - Full folder/file path name
         * @param host - machine to connect to
         * @param user
         * @param pass
         */
        public static boolean changeFilePermissionsToReadWrite() {
            
            GregorianCalendar calendar = new GregorianCalendar();
            String today = (calendar.get(calendar.MONTH)+1) + "-" + calendar.get(calendar.DAY_OF_MONTH) + "-" + calendar.get(calendar.YEAR);
            
            
           String host = "alcott.hul.harvard.edu";
           String user = "";
           String pass = "";
           String fileName = "/mnt/pratchett/hgl_asynch/prod/clips/" + today;
            boolean wasMade = false;                                                 
            try {
                Connection conn = new Connection(host);
                conn.connect();
                boolean isAuthenticated = conn.authenticateWithPassword(user, pass);

                if (isAuthenticated == false)
                    throw new IOException("Authentication failed.");

                Session sess = conn.openSession();
                            sess.execCommand("chmod a+rw "+ fileName );
                InputStream stdout = new StreamGobbler(sess.getStdout());
                BufferedReader br = new BufferedReader(new InputStreamReader(stdout));

                while (true) {
                    String line = br.readLine();
                    if (line == null)
                        break;
                    System.out.println(line);
                }

                sess.close();
                conn.close();

            } catch (IOException e) {
                e.printStackTrace(System.err);
                System.exit(2);
            }

            
            // 3. Validate that the raster was clipped and send + or - back
            File aFile = new File(fileName);
            if (aFile.canWrite()) 
               return true;
             else
               return false;
          
        }
        
}